package main

import (
	"bufio"
	"encoding/json"
	"fmt"
	"os"
	"sort"
	"strconv"
	"strings"
)

// User 定义用户结构体
type User struct {
	Username string
	Password string
}

// Student 定义学生结构体，包含多科成绩
type Student struct {
	ID       string
	Name     string
	Subjects map[string]int // 科目成绩映射
	Total    int            // 总分
}

// 定义各科目满分
var subjectFullMarks = map[string]int{
	"数学":    150,
	"语文":    150,
	"英语":    150,
	"历史":    50,
	"地理":    50,
	"化学":    100,
	"物理":    100,
	"道德与法治": 50,
}

// 用户数据库
var users []User

// 学生成绩数据库
var students []Student

// 当前登录用户
var currentUser string

// 保存用户数据到文件
func saveUsers() {
	file, err := os.Create("users.json")
	if err != nil {
		fmt.Println("保存用户数据时出错:", err)
		return
	}
	defer file.Close()

	encoder := json.NewEncoder(file)
	err = encoder.Encode(users)
	if err != nil {
		fmt.Println("编码用户数据时出错:", err)
	}
}

// 加载用户数据从文件
func loadUsers() {
	file, err := os.Open("users.json")
	if err != nil {
		if os.IsNotExist(err) {
			// 文件不存在，初始化空用户列表
			users = []User{}
			return
		}
		fmt.Println("加载用户数据时出错:", err)
		return
	}
	defer file.Close()

	decoder := json.NewDecoder(file)
	err = decoder.Decode(&users)
	if err != nil {
		fmt.Println("解码用户数据时出错:", err)
	}
}

// 保存学生成绩数据到文件
func saveStudents() {
	file, err := os.Create("students.json")
	if err != nil {
		fmt.Println("保存学生成绩数据时出错:", err)
		return
	}
	defer file.Close()

	encoder := json.NewEncoder(file)
	err = encoder.Encode(students)
	if err != nil {
		fmt.Println("编码学生成绩数据时出错:", err)
	}
}

// 加载学生成绩数据从文件
func loadStudents() {
	file, err := os.Open("students.json")
	if err != nil {
		if os.IsNotExist(err) {
			// 文件不存在，初始化空学生列表
			students = []Student{}
			return
		}
		fmt.Println("加载学生成绩数据时出错:", err)
		return
	}
	defer file.Close()

	decoder := json.NewDecoder(file)
	err = decoder.Decode(&students)
	if err != nil {
		fmt.Println("解码学生成绩数据时出错:", err)
	}
}

// 检查成绩是否在满分范围内
func checkGradeValid(subject string, grade int) bool {
	fullMark, exists := subjectFullMarks[subject]
	return exists && grade >= 0 && grade <= fullMark
}

// 注册功能
func register() {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("请输入用户名: ")
	username, _ := reader.ReadString('\n')
	username = strings.TrimSpace(username)

	for _, user := range users {
		if user.Username == username {
			fmt.Println("用户名已存在，请选择其他用户名。")
			return
		}
	}

	fmt.Print("请输入密码: ")
	password, _ := reader.ReadString('\n')
	password = strings.TrimSpace(password)

	newUser := User{
		Username: username,
		Password: password,
	}
	users = append(users, newUser)
	saveUsers()
	fmt.Println("注册成功！")
}

// 登录功能
func login() {
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("请输入用户名: ")
	username, _ := reader.ReadString('\n')
	username = strings.TrimSpace(username)

	fmt.Print("请输入密码: ")
	password, _ := reader.ReadString('\n')
	password = strings.TrimSpace(password)

	userExists := false
	for _, user := range users {
		if user.Username == username {
			userExists = true
			if user.Password == password {
				currentUser = username
				fmt.Println("登录成功！")
				return
			}
		}
	}
	if !userExists {
		fmt.Println("没有该用户，请先注册。")
	} else {
		fmt.Println("用户名或密码错误。")
	}
}

// 退出登录功能
func logout() {
	if currentUser == "" {
		fmt.Println("你尚未登录。")
		return
	}
	currentUser = ""
	fmt.Println("退出登录成功！")
}

// 一键录入成绩功能，可录入多科成绩，且不可重复录入相同科目
func enterGrade() {
	if currentUser == "" {
		fmt.Println("你需要先登录才能录入成绩。")
		return
	}
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("请输入学生 ID: ")
	id, _ := reader.ReadString('\n')
	id = strings.TrimSpace(id)

	fmt.Print("请输入学生姓名: ")
	name, _ := reader.ReadString('\n')
	name = strings.TrimSpace(name)

	subjects := make(map[string]int)
	total := 0

	fmt.Println("请输入科目和成绩，格式为：科目1 成绩1 科目2 成绩2 ...（输入 '结束' 完成录入）")
	input, _ := reader.ReadString('\n')
	input = strings.TrimSpace(input)
	if input == "结束" {
		fmt.Println("未录入任何成绩。")
		return
	}

	parts := strings.Fields(input)
	if len(parts)%2 != 0 {
		fmt.Println("输入格式错误，请确保科目和成绩成对输入。")
		return
	}

	for i := 0; i < len(parts); i += 2 {
		subject := parts[i]
		gradeStr := parts[i+1]

		if _, exists := subjectFullMarks[subject]; !exists {
			fmt.Printf("科目 %s 不存在，跳过该科目。\n", subject)
			continue
		}
		if _, exists := subjects[subject]; exists {
			fmt.Printf("科目 %s 已录入，跳过该科目。\n", subject)
			continue
		}

		grade, err := strconv.Atoi(gradeStr)
		if err != nil || !checkGradeValid(subject, grade) {
			fmt.Printf("%s 科目满分是 %d 分，请输入有效的成绩，跳过该科目。\n", subject, subjectFullMarks[subject])
			continue
		}

		subjects[subject] = grade
		total += grade
	}

	if len(subjects) == 0 {
		fmt.Println("未成功录入任何有效成绩。")
		return
	}

	newStudent := Student{
		ID:       id,
		Name:     name,
		Subjects: subjects,
		Total:    total,
	}
	students = append(students, newStudent)
	saveStudents()
	fmt.Println("成绩录入成功！")
}

// 搜索成绩功能
func searchGrade() {
	if currentUser == "" {
		fmt.Println("你需要先登录才能搜索成绩。")
		return
	}
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("请输入要搜索的学生 ID 或姓名: ")
	keyword, _ := reader.ReadString('\n')
	keyword = strings.TrimSpace(keyword)

	found := false
	for _, student := range students {
		if student.ID == keyword || student.Name == keyword {
			fmt.Printf("学生 ID: %s, 姓名: %s\n", student.ID, student.Name)
			for subject, grade := range student.Subjects {
				fmt.Printf("%s 成绩: %d (满分 %d)\n", subject, grade, subjectFullMarks[subject])
			}
			fmt.Printf("总分: %d\n", student.Total)
			found = true
		}
	}
	if !found {
		fmt.Println("未找到相关学生信息。")
	}
}

// 个人信息功能
func personalInfo() {
	if currentUser == "" {
		fmt.Println("你需要先登录才能查看个人信息。")
		return
	}
	fmt.Printf("当前登录用户: %s\n", currentUser)
}

// 修改成绩功能
func modifyGrade() {
	if currentUser == "" {
		fmt.Println("你需要先登录才能修改成绩。")
		return
	}
	reader := bufio.NewReader(os.Stdin)
	fmt.Print("请输入要修改成绩的学生 ID 或姓名: ")
	keyword, _ := reader.ReadString('\n')
	keyword = strings.TrimSpace(keyword)

	found := false
	for i, student := range students {
		if student.ID == keyword || student.Name == keyword {
			fmt.Printf("学生 ID: %s, 姓名: %s\n", student.ID, student.Name)
			for subject, grade := range student.Subjects {
				fmt.Printf("%s 成绩: %d (满分 %d)\n", subject, grade, subjectFullMarks[subject])
			}
			fmt.Print("请输入要修改成绩的科目: ")
			subject, _ := reader.ReadString('\n')
			subject = strings.TrimSpace(subject)
			if _, ok := student.Subjects[subject]; ok {
				var newGrade int
				for {
					fmt.Printf("请输入 %s 的新成绩: ", subject)
					fmt.Scanln(&newGrade)
					if checkGradeValid(subject, newGrade) {
						break
					}
					fmt.Printf("%s 科目满分是 %d 分，请输入有效的成绩。\n", subject, subjectFullMarks[subject])
				}
				oldGrade := student.Subjects[subject]
				student.Subjects[subject] = newGrade
				student.Total = student.Total - oldGrade + newGrade
				students[i] = student
				saveStudents()
				fmt.Println("成绩修改成功！")
			} else {
				fmt.Println("该学生没有此科目成绩。")
			}
			found = true
			break
		}
	}
	if !found {
		fmt.Println("未找到相关学生信息。")
	}
}

// 总分排名榜功能
func totalScoreRanking() {
	if currentUser == "" {
		fmt.Println("你需要先登录才能查看总分排名榜。")
		return
	}
	sortedStudents := make([]Student, len(students))
	copy(sortedStudents, students)
	sort.Slice(sortedStudents, func(i, j int) bool {
		return sortedStudents[i].Total > sortedStudents[j].Total
	})

	fmt.Println("总分排名榜：")
	for rank, student := range sortedStudents {
		fmt.Printf("%d. 学生 ID: %s, 姓名: %s, 总分: %d\n", rank+1, student.ID, student.Name, student.Total)
	}
}

func main() {
	loadUsers()
	loadStudents()

	for {
		fmt.Println("\n请选择操作:")
		fmt.Println("1. 注册")
		fmt.Println("2. 登录")
		fmt.Println("3. 退出登录")
		fmt.Println("4. 录入成绩")
		fmt.Println("5. 搜索成绩")
		fmt.Println("6. 个人信息")
		fmt.Println("7. 修改成绩")
		fmt.Println("8. 总分排名榜")
		fmt.Println("9. 退出系统")

		var choice int
		fmt.Print("请输入选项编号: ")
		fmt.Scanln(&choice)

		switch choice {
		case 1:
			register()
		case 2:
			login()
		case 3:
			logout()
		case 4:
			enterGrade()
		case 5:
			searchGrade()
		case 6:
			personalInfo()
		case 7:
			modifyGrade()
		case 8:
			totalScoreRanking()
		case 9:
			fmt.Println("退出系统。")
			return
		default:
			fmt.Println("无效的选项，请重新输入。")
		}
	}
}
